﻿using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DependencyRules.RowModel;
using Kingdee.BOS.Core.DependencyRules;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.Metadata.Expression.FuncDefine;
using Kingdee.BOS.Core.Metadata.Expression;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Core.Metadata.Util;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.SqlBuilder;
using Kingdee.BOS.Core.Util;
using Kingdee.BOS.FileServer.ProxyService;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Scripting;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS;
using Kingdee.BOS.Util;
using Kingdee.BOS.WebApi.FormService;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.CSharp.RuntimeBinder;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Kingdee.BOS.JSON;
using RK.Model.Common;

namespace RK.Tools
{
    [Description("金蝶和第三方系统同步工具类")]
    [HotUpdate]
    public class KAndOSysSynTool
    {
        public static string GetLcUrl(DynamicObject setting)
        {
            string url = Convert.ToString(setting["FLct"]);
            return url;
        }
        public static string GetUrl(DynamicObject setting, string port)
        {
            string url = Convert.ToString(setting["OSysURL"]);
            if (url.IsNullOrEmptyOrWhiteSpace())
            {
                throw new Exception("获取第三方系统同步地址为空，无法同步！");
            }
            if (url.EndsWith("/"))
            {
                url += port.StartsWith("/") ? port.Substring(1) : port;
            }
            else
            {
                url += port.StartsWith("/") ? port : "/" + port;
            }
            return url;
        }

        #region 金蝶到第三方系统同步操作设置
        /// <summary>
        /// 金蝶到第三方系统同步操作设置
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="formId">业务对象</param>
        /// <returns></returns>
        public static DynamicObject[] GetKToOSysSynOpSts(Context context, string formId, long useOrgId)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynOpSt");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynOpSt";
            queryParam.FilterClauseWihtKey = string.Format(@" FSynDirection='1' and FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FFormId='{0}' 
				--and FUseOrgId={1} ", formId, useOrgId);
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            return objs;
        }

        /// <summary>
        /// 获取金蝶同步第三方系统操作配置
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="useOrgId"></param>
        /// <param name="operationNumber"></param>
        /// <returns></returns>
        public static DynamicObject GetKToOSysSynOp(Context context, string formId, long useOrgId, string operationNumber)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynOpSt");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynOpSt";
            queryParam.FilterClauseWihtKey = string.Format(@" FSynDirection='1' and FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FFormId='{0}' 
				--and FUseOrgId={1} 
				and FOperationNumber='{2}' and FIsSyn=1 ", formId, useOrgId, operationNumber);
            queryParam.OrderByClauseWihtKey = " FAPPROVEDATE desc ";//按审核日期逆序
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs != null && objs.Count() > 0)
            {
                DynamicObject obj = objs.First();
                DynamicObjectCollection rows = obj["FEntity"] as DynamicObjectCollection;
                var findRows = rows.Where(w => Convert.ToString(w["OperationNumber"]).EqualsIgnoreCase(operationNumber));
                return findRows.First();
            }
            return null;
        }
        #endregion

        /// <summary>
        /// 获取金蝶同步第三方系统操作配置
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="useOrgId"></param>
        /// <param name="operationNumber"></param>
        /// <param name="synNodeType">同步节点类型:1操作前，2操作后，3事务开始中，4事务结束中</param>
        /// <returns></returns>
        public static List<DynamicObject> GetKToOSysSynOps(Context context, string formId, long useOrgId, string operationNumber, int synNodeType)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynOpSt");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynOpSt";
            queryParam.FilterClauseWihtKey = string.Format(@" FSynDirection='1' and FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FFormId='{0}' 
				--and FUseOrgId={1} 
				and FOperationNumber='{2}' and FIsSyn=1 and FIsSynNode='{3}'", formId, useOrgId, operationNumber, synNodeType);
            queryParam.OrderByClauseWihtKey = " FAPPROVEDATE desc ";//按审核日期逆序
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs != null && objs.Count() > 0)
            {
                DynamicObject obj = objs.First();
                DynamicObjectCollection rows = obj["FEntity"] as DynamicObjectCollection;
                var findRows = rows.Where(w => Convert.ToString(w["OperationNumber"]).EqualsIgnoreCase(operationNumber));
                if (findRows.Count() > 0)
                {
                    return findRows.ToList();

                }
                return null;
            }
            return null;
        }

        /// <summary>
        /// 获取金蝶同步第三方系统操作配置
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="useOrgId"></param>
        /// <param name="operationNumber"></param>
        /// <param name="synNodeType">同步节点类型:1操作前，2操作后，3事务开始中，4事务结束中</param>
        /// <param name="isSynType">同步类型1：状态 2：数据</param>
        /// <returns></returns>
        public static List<DynamicObject> GetKToOSysSynOps(Context context, string formId, long useOrgId, string operationNumber, int synNodeType, string isSynType)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynOpSt");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynOpSt";
            queryParam.FilterClauseWihtKey = string.Format(@" FSynDirection='1' and FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FFormId='{0}' 
				--and FUseOrgId={1} 
				and FOperationNumber='{2}' and FIsSyn=1 and FIsSynNode='{3}' and FIsSynType='{4}'", formId, useOrgId, operationNumber, synNodeType, isSynType);
            queryParam.OrderByClauseWihtKey = " FAPPROVEDATE desc ";//按审核日期逆序
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs != null && objs.Count() > 0)
            {
                DynamicObject obj = objs.First();
                DynamicObjectCollection rows = obj["FEntity"] as DynamicObjectCollection;
                var findRows = rows.Where(w => Convert.ToString(w["OperationNumber"]).EqualsIgnoreCase(operationNumber));
                if (findRows.Count() > 0)
                {
                    return findRows.ToList();

                }
                return null;
            }
            return null;
        }

        /// <summary>
        /// 获取同步设置，获取组织所有设置，如果存在多行就增加表单Id去找到指定业务对象同步设置
        /// </summary>
        /// <param name="context"></param>
        /// <param name="formId"></param>
        /// <param name="orgId"></param>
        /// <returns></returns>
        public static DynamicObject GetKToOSysSynSetting(Context context, string formId, long orgId)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynSet");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynSet";
            //queryParam.FilterClauseWihtKey = string.Format(" FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FUSEORGID={0}", orgId);
            queryParam.FilterClauseWihtKey = string.Format(" FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' ");
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            if (objs.Length > 1)
            {
                var findRows = objs.Where(w => (w["FormId"] as DynamicObject) != null && Convert.ToString((w["FormId"] as DynamicObject)["id"]).EqualsIgnoreCase(formId));
                if (findRows != null && findRows.Count() > 0)
                {
                    return findRows.First();
                }
            }
            else if (objs.Length == 1)
            {
                return objs.First();

            }
            return null;
        }

        /// <summary>
        /// 获取金蝶和第三方系统同步映射配置，1是金蝶到第三方系统，2是第三方系统到金蝶
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="formId">业务对象</param>
        /// <param name="synDirection">同步方向：1是金蝶到第三方系统，2是第三方系统到金蝶</param>
        /// <returns></returns>
        public static DynamicObject GetKAndOSysSynMap(Context context, string formId, int synDirection)
        {
            var objs = GetKAndOSysSynMaps(context, formId, synDirection);
            if (objs != null && objs.Count() > 0)
            {
                return objs.Last();
            }
            return null;
        }

        /// <summary>
        /// 获取金蝶和第三方系统同步映射配置
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="formId">业务对象</param>
        /// <param name="synDirection">同步方向：1是金蝶到第三方系统，2是第三方系统到金蝶</param>
        /// <returns></returns>
        public static DynamicObject[] GetKAndOSysSynMaps(Context context, string formId, int synDirection)
        {
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(context, "qqq_KAndOSysSynMap");
            QueryBuilderParemeter queryParam = new QueryBuilderParemeter();
            queryParam.FormId = "qqq_KAndOSysSynMap";
            queryParam.FilterClauseWihtKey = string.Format(" FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A' and FFormId='{0}' and FSynDirection='{1}'", formId, synDirection);
            var objs = BusinessDataServiceHelper.Load(context, meta.BusinessInfo.GetDynamicObjectType(), queryParam);
            return objs;
        }

        #region 金蝶到第三方映射处理
        public static JSONObject GetObjByK3(IDynamicFormView view, DynamicObject map)
        {
            DynamicObjectCollection entitys = map["FEntity"] as DynamicObjectCollection;
            OSysNode oSysNode = CreateOSysNode(entitys);
            return CreateOSysJson(view, oSysNode);
        }

        //按节点展开生成同步到第三方系统JSON
        public static JSONObject CreateOSysJson(IDynamicFormView view, OSysNode oSysNode)
        {
            JSONObject orderJson = new JSONObject();
            //展开第一级
            if (oSysNode.Fields.Count > 0)
            {
                foreach (var fieldObject in oSysNode.Fields)
                {
                    string oSysColumnKey = Convert.ToString(fieldObject["OSysColumnKey"]);

                    orderJson.Add(oSysColumnKey, GetK3HeadExpressionValue(view, fieldObject));
                }
            }
            //展开第二级
            if (oSysNode.ChildOSysNodes.Count > 0)
            {
                foreach (var childOSysNode in oSysNode.ChildOSysNodes)
                {
                    if (childOSysNode.Fields.Count > 0)
                    {

                        var findK3EntityKeys = childOSysNode.Fields.Select(s => Convert.ToString(s["KSysEntityKey"])).Distinct().Where(w => !w.IsNullOrEmptyOrWhiteSpace());
                        if (findK3EntityKeys.Count() == 1)
                        {
                            string findK3EntityKey = findK3EntityKeys.First();
                            //单据头
                            if (findK3EntityKey.EqualsIgnoreCase("FBillHead"))
                            {
                                Dictionary<string, DynamicObject> id_Obj = new Dictionary<string, DynamicObject>();
                                id_Obj.Add(oSysNode.OSysEntityKey, view.Model.DataObject);

                                JSONObject rowObjs = new JSONObject();
                                foreach (var fieldObject in childOSysNode.Fields)
                                {
                                    string oSysColumnKey = Convert.ToString(fieldObject["OSysColumnKey"]);
                                    rowObjs.Add(oSysColumnKey, GetK3HeadExpressionValue(view, fieldObject));
                                }
                                orderJson.Add(childOSysNode.OSysEntityKey, rowObjs);
                            }
                            //单据体
                            else
                            {
                                JSONArray array = new JSONArray();
                                Entity entity = view.BusinessInfo.GetEntity(findK3EntityKey);
                                DynamicObjectCollection rows = entity.DynamicProperty.GetValue(view.Model.DataObject) as DynamicObjectCollection; //view.Model.GetEntityDataObject(entity);
                                for (int i = 0; i < rows.Count; i++)
                                {
                                    Dictionary<string, DynamicObject> id_Obj = new Dictionary<string, DynamicObject>();
                                    id_Obj.Add(oSysNode.OSysEntityKey, view.Model.DataObject);

                                    JSONObject rowObjs = new JSONObject();
                                    foreach (var fieldObject in childOSysNode.Fields)
                                    {
                                        string oSysColumnKey = Convert.ToString(fieldObject["OSysColumnKey"]);
                                        rowObjs.Add(oSysColumnKey, GetK3EntityExpressionValue(view, i, fieldObject, id_Obj));
                                    }
                                    id_Obj.Add(childOSysNode.OSysEntityKey, rows[i]);
                                    CreateOSysEntryJson(view, rows[i], childOSysNode, rowObjs, id_Obj);
                                    array.Add(rowObjs);
                                }
                                orderJson.Add(childOSysNode.OSysEntityKey, array);
                            }

                        }
                        else if (findK3EntityKeys.Count() < 1)
                        {
                            throw new Exception(string.Format("获取不到第三方系统节点【{0}】对应的金蝶单据体，请检查映射配置!", childOSysNode.OSysEntityKey));
                        }
                        else if (findK3EntityKeys.Count() > 1)
                        {
                            throw new Exception(string.Format("第三方系统节点【{0}】获取到多个金蝶单据体【{1}】，请检查映射配置!", childOSysNode.OSysEntityKey
                                , string.Join("、", findK3EntityKeys)));
                        }
                    }
                }
            }


            return orderJson;
        }
        //递归生成子单据体JSON对象，不支持表达式
        public static void CreateOSysEntryJson(IDynamicFormView view, DynamicObject row, OSysNode oSysNode, JSONObject orderRowsJson, Dictionary<string, DynamicObject> id_Obj)
        {
            if (oSysNode.ChildOSysNodes.Count > 0)
            {
                foreach (var childOSysNode in oSysNode.ChildOSysNodes)
                {
                    JSONArray array = new JSONArray();
                    if (childOSysNode.Fields.Count > 0)
                    {
                        if (childOSysNode.Fields.Where(s => Convert.ToString(s["MapType"]).EqualsIgnoreCase("2")).Count() > 0)
                        {
                            throw new Exception(string.Format("第3层开始不支持使用表达式，当前节点【{0}】", childOSysNode.OSysEntityKey));
                        }
                        var findK3EntityKeys = childOSysNode.Fields.Select(s => Convert.ToString(s["KSysEntityKey"])).Distinct().Where(w => !w.IsNullOrEmptyOrWhiteSpace()
                            && !id_Obj.ContainsKey(w)
                        );
                        if (findK3EntityKeys.Count() == 1)
                        {
                            string findK3EntityKey = findK3EntityKeys.First();
                            SubEntryEntity entity = view.BusinessInfo.GetEntity(findK3EntityKey) as SubEntryEntity;
                            DynamicObjectCollection rows = null;// entity.DynamicProperty.GetValue<DynamicObjectCollection>(row);
                            if (KingdeeTools.IsContainsKey(row, entity.EntryName))
                            {
                                rows = entity.DynamicProperty.GetValue<DynamicObjectCollection>(row);
                            }
                            //单据体节点标识容错
                            else
                            {
                                var findDyObjs = id_Obj.Values.Where(w => KingdeeTools.IsContainsKey(w, entity.EntryName));
                                if (findDyObjs != null && findDyObjs.Count() == 1)
                                {
                                    rows = entity.DynamicProperty.GetValue<DynamicObjectCollection>(findDyObjs.First());
                                }
                                else
                                {
                                    throw new Exception(string.Format("获取不到包含单据体【{0}】的数据对象!", findK3EntityKey));
                                }
                            }
                            for (int i = 0; i < rows.Count; i++)
                            {
                                Dictionary<string, DynamicObject> newId_Obj = new Dictionary<string, DynamicObject>(id_Obj);
                                JSONObject rowObjs = new JSONObject();
                                foreach (var fieldObject in childOSysNode.Fields)
                                {
                                    string oSysColumnKey = Convert.ToString(fieldObject["OSysColumnKey"]);
                                    string kSysColumnKey = Convert.ToString(fieldObject["KSysColumnKey"]);
                                    object o = GetMultilayerFieldValue(view, findK3EntityKey, kSysColumnKey, rows[i], id_Obj);
                                    rowObjs.Add(oSysColumnKey, o);
                                }
                                newId_Obj.Add(childOSysNode.OSysEntityKey, rows[i]);
                                CreateOSysEntryJson(view, rows[i], childOSysNode, rowObjs, newId_Obj);
                                array.Add(rowObjs);
                            }
                            orderRowsJson.Add(childOSysNode.OSysEntityKey, array);
                        }
                        else if (findK3EntityKeys.Count() < 1)
                        {
                            throw new Exception(string.Format("获取不到第三方系统节点【{0}】对应的金蝶单据体，请检查映射配置!", childOSysNode.OSysEntityKey));
                        }
                        else if (findK3EntityKeys.Count() > 1)
                        {
                            throw new Exception(string.Format("第三方系统节点【{0}】获取到多个金蝶单据体【{1}】，请检查映射配置!", childOSysNode.OSysEntityKey
                                , string.Join("、", findK3EntityKeys)));
                        }
                    }


                }
            }
        }


        /// <summary>
        /// 解析多级列值(.实体属性 分开)
        /// </summary>
        /// <param name="view"></param>
        /// <param name="curK3EntityKey"></param>
        /// <param name="kSysColumnKey"></param>
        /// <param name="row"></param>
        /// <param name="id_Obj"></param>
        /// <returns></returns>
        public static object GetMultilayerFieldValue(IDynamicFormView view, string curK3EntityKey, string kSysColumnKey, DynamicObject row, Dictionary<string, DynamicObject> id_Obj)
        {
            //用.区分是取哪个列的值
            string[] kSysColumnKeys = kSysColumnKey.Split('.');
            int count = kSysColumnKeys.Count();
            Field field = view.BusinessInfo.GetField(kSysColumnKeys.First());
            object v = null;
            if (field.EntityKey.EqualsIgnoreCase(curK3EntityKey))
            {
                v = field.GetFieldValue(row);
            }
            else if (id_Obj != null && id_Obj.ContainsKey(field.EntityKey))
            {
                v = field.GetFieldValue(id_Obj[field.EntityKey]);
            }
            else
            {
                throw new Exception(string.Format("单据体【{0}】和上级单据体中找不到列【{1}】", curK3EntityKey, kSysColumnKey));
            }
            return GetFieldValue(v, field, kSysColumnKeys);

        }

        /// <summary>
        /// 解析多级列值(.实体属性 分开)
        /// </summary>
        /// <param name="view"></param>
        /// <param name="curK3EntityKey"></param>
        /// <param name="kSysColumnKey"></param>
        /// <param name="row"></param>
        /// <param name="id_Obj"></param>
        /// <returns></returns>
        public static object GetTowMultilayerFieldValue(IDynamicFormView view, string kSysColumnKey, int rowIndex)
        {
            //用.区分是取哪个列的值
            string[] kSysColumnKeys = kSysColumnKey.Split('.');
            int count = kSysColumnKeys.Count();
            object v = view.Model.GetValue(kSysColumnKeys.First(), rowIndex);
            Field field = view.BusinessInfo.GetField(kSysColumnKeys.First());
            return GetFieldValue(v, field, kSysColumnKeys);

        }

        public static object GetFieldValue(object v, Field field, string[] kSysColumnKeys)
        {
            if (v == null)
            {
                return v;
            }
            int count = kSysColumnKeys.Count();
            //基础资料或者单选辅助资料
            if (field is BaseDataField || field is AssistantField)
            {
                if (count > 1 && v != null)
                {
                    return GetAnalyzeColumnValue(v, kSysColumnKeys, 1);
                }
            }
            //日期类型，日期列.日期格式
            else if (field is DateField || field is DateTimeField)
            {
                if (count > 1)
                {
                    return Convert.ToDateTime(v).ToString(kSysColumnKeys[1]);
                }
            }
            //多语言文本
            else if (field is MultiLangTextField)
            {
                return (v as LocaleValue).GetString(2052);
            }
            //下拉列表,如果包含"."，则用名称
            else if (field is ComboField && count > 1)
            {
                if (count > 0)
                {
                    ComboField comboField = field as ComboField;
                    return comboField.GetEnumItemName(v);
                }
            }
            //辅助属性
            else if (field is RelatedFlexGroupField && count > 1)
            {
                return GetAnalyzeColumnValue(v, kSysColumnKeys, 1);
            }
            //string kSysEntityKey = Convert.ToString(fieldObject["KSysEntityKey"]);
            return v;
        }

        /// <summary>
        /// 递归解析列的值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="kSysColumnKeys"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        public static object GetAnalyzeColumnValue(object obj, string[] kSysColumnKeys, int i)
        {
            if (obj != null)
            {
                DynamicObject o = null;

                if (obj is DynamicObjectCollection)
                {
                    o = (obj as DynamicObjectCollection).First();
                }
                else
                {
                    o = obj as DynamicObject;
                }
                if (o == null)
                {
                    return null;
                }
                else
                {
                    if (i + 1 != kSysColumnKeys.Count())
                    {
                        return GetAnalyzeColumnValue(o[kSysColumnKeys[i]], kSysColumnKeys, i + 1);
                    }
                    else
                    {
                        object co = o[kSysColumnKeys[i]];
                        if (co != null && co is LocaleValue)
                        {
                            return (co as LocaleValue).GetString(2052);
                        }
                        return co;

                    }
                }
            }
            else
            {
                return null;
            }
        }


        /// <summary>
        /// 获取第三方系统节点，空白为第1级,有文本为第2级,文本.节点为第3级
        /// </summary>
        /// <param name="entitys"></param>
        /// <returns></returns>
        public static OSysNode CreateOSysNode(DynamicObjectCollection entitys)
        {
            var firstNode = entitys.Where(w => Convert.ToString(w["OSysEntityKey"]).Trim().IsNullOrEmptyOrWhiteSpace());
            //获取第1级
            OSysNode node = new OSysNode();
            node.OSysEntityKey = "";
            node.ChildOSysNodes = new List<OSysNode>();
            node.Fields = new List<DynamicObject>();
            if (firstNode.Count() > 0)
            {
                node.Fields = firstNode.OrderBy(o => Convert.ToInt32(o["Seq"])).ToList();

            }
            //获取第2级
            var secondNodes = entitys.Where(w => !Convert.ToString(w["OSysEntityKey"]).Trim().IsNullOrEmptyOrWhiteSpace() && !Convert.ToString(w["OSysEntityKey"]).Contains("."));
            if (secondNodes.Count() > 0)
            {
                var secondNodeDic = secondNodes.GroupBy(g => Convert.ToString(g["OSysEntityKey"])).ToDictionary(t => t.Key, t => t.ToList());
                foreach (var secondNodeKey in secondNodeDic.Keys)
                {
                    OSysNode childNode = new OSysNode()
                    {
                        OSysEntityKey = secondNodeKey
                            ,
                        ChildOSysNodes = new List<OSysNode>()
                            ,
                        Fields = secondNodeDic[secondNodeKey].OrderBy(o => Convert.ToInt32(o["Seq"])).ToList()
                    };
                    AddOSysEntryEntity(entitys, childNode);
                    node.ChildOSysNodes.Add(childNode);
                }
            }
            return node;
        }

        /// <summary>
        /// 递归创建第三方系统第N级节点
        /// </summary>
        /// <param name="entitys"></param>
        /// <param name="node"></param>
        private static void AddOSysEntryEntity(DynamicObjectCollection entitys, OSysNode node)
        {
            //判断是否包含下级
            var childNodes = entitys.Where(w => Convert.ToString(w["OSysEntityKey"]).StartsWith(node.OSysEntityKey)
            && Convert.ToString(w["OSysEntityKey"]).Split('.').Count() == node.OSysEntityKey.Split('.').Count() + 1);
            if (childNodes.Count() > 0)
            {
                var nNodeDic = childNodes.GroupBy(g => Convert.ToString(g["OSysEntityKey"])).ToDictionary(t => t.Key, t => t.ToList());
                foreach (var nNodeKey in nNodeDic.Keys)
                {
                    OSysNode childNode = new OSysNode()
                    {
                        OSysEntityKey = nNodeKey.Split('.').Last()
                            ,
                        ChildOSysNodes = new List<OSysNode>()
                            ,
                        Fields = nNodeDic[nNodeKey].OrderBy(o => Convert.ToInt32(o["Seq"])).ToList()
                    };
                    AddOSysEntryEntity(entitys, childNode);
                    node.ChildOSysNodes.Add(childNode);
                }
            }
        }


        public static void SetFieldValueByK3(JSONObject obj, DynamicObject d)
        {

        }

        /// <summary>
        /// 获取单据头的值
        /// </summary>
        /// <param name="view"></param>
        /// <param name="mapRow"></param>
        /// <returns></returns>
        public static object GetK3HeadExpressionValue(IDynamicFormView view, DynamicObject mapRow)
        {
            string mapType = Convert.ToString(mapRow["MapType"]);
            if (mapType.EqualsIgnoreCase("2"))
            {
                string entityKey = Convert.ToString(mapRow["KSysEntityKey"]);
                string pyExpression = Convert.ToString(mapRow["KTOExpression"]);
                return ExecutionExpression(view, 0, entityKey, pyExpression);

            }
            else if (mapType.EqualsIgnoreCase("1"))
            {
                return mapRow["KSysColumnName"];

            }
            //附件
            else if (mapType.EqualsIgnoreCase("3"))
            {

                DynamicObject[] attachments = KingdeeTools.GetAttachments(view.Context, view.BusinessInfo.GetForm().Id, view.Model.DataObject["id"]);
                if (attachments.Count() > 0)
                {
                    List<string> list = new List<string>();
                    UpDownloadService fileService = new UpDownloadService();
                    List<string> names = new List<string>();
                    List<JSONObject> o = new List<JSONObject>();
                    foreach (var attachment in attachments)
                    {

                        JSONObject o2 = new JSONObject();
                        //string str = "base64:" + KingdeeTools.GetAttachmentBase64(view.Context, attachment, fileService);
                        string str = KingdeeTools.GetAttachmentBase64(view.Context, attachment, fileService);
                        list.Add(str);
                        //attachmentStrs.Add(str);
                        string name = Convert.ToString(attachment["AttachmentName"]);
                        names.Add(name);
                        o2.Add("filePath", str);
                        o2.Add("fileName", name);
                        o.Add(o2);
                    }
                    //JSONObject o = new JSONObject();
                    //string filePath = string.Join(";", attachmentStrs);
                    //o.Add("filePath", filePath);
                    //string fileName = string.Join(";", names);
                    //o.Add("fileName", fileName);
                    return string.Join(",", list.ToArray());
                }
                return "";
            }
            //SQL查询值
            else if (mapType.EqualsIgnoreCase("4"))
            {
                string kSysColumnKey = Convert.ToString(mapRow["KSysColumnKey"]);
                object o = GetTowMultilayerFieldValue(view, kSysColumnKey, 0);
                //为空直接返回
                if (o.IsNullOrEmptyOrWhiteSpace())
                {
                    return "";
                }
                //从表达式获取sql
                string sql = Convert.ToString(mapRow["KTOExpression"]);
                //为空直接返回值
                if (sql.IsNullOrEmptyOrWhiteSpace())
                {
                    return o;
                }
                SqlParam[] sqlParams = new SqlParam[] {
                            new SqlParam("@value",KDDbType.String,Convert.ToString(o))
                        };
                string v = DBUtils.ExecuteScalar<string>(view.Context, sql, "", sqlParams);
                return v;
            }
            else
            {
                string kSysColumnKey = Convert.ToString(mapRow["KSysColumnKey"]);
                object o = GetTowMultilayerFieldValue(view, kSysColumnKey, 0);
                return o;
            }


        }

        /// <summary>
        /// 获取明细的值
        /// </summary>
        /// <param name="view"></param>
        /// <param name="mapRow"></param>
        /// <returns></returns>
        public static object GetK3EntityExpressionValue(IDynamicFormView view, int rowIndex, DynamicObject mapRow, Dictionary<string, DynamicObject> id_Obj)
        {
            string mapType = Convert.ToString(mapRow["MapType"]);
            if (mapType.EqualsIgnoreCase("2"))
            {
                string entityKey = Convert.ToString(mapRow["KSysEntityKey"]);
                string pyExpression = Convert.ToString(mapRow["KTOExpression"]);
                return ExecutionExpression(view, rowIndex, entityKey, pyExpression);

            }
            else if (mapType.EqualsIgnoreCase("1"))
            {
                return mapRow["KSysColumnName"];

            }
            //附件
            else if (mapType.EqualsIgnoreCase("3"))
            {
                DynamicObject[] attachments = KingdeeTools.GetAttachments(view.Context, view.BusinessInfo.GetForm().Id, view.Model.DataObject["id"]);
                if (attachments.Count() > 0)
                {
                    List<string> attachmentStrs = new List<string>();
                    UpDownloadService fileService = new UpDownloadService();
                    List<string> names = new List<string>();
                    foreach (var attachment in attachments)
                    {
                        string str = KingdeeTools.GetAttachmentBase64(view.Context, attachment, fileService);
                        attachmentStrs.Add(str);
                        string name = Convert.ToString(attachment["AttachmentName"]);
                        names.Add(name);
                    }
                    JSONObject o = new JSONObject();
                    string filePath = string.Join(";", attachmentStrs);
                    o.Add("filePath", filePath);
                    string fileName = string.Join(";", names);
                    o.Add("fileName", fileName);
                    return o;
                }
                return "";
            }
            //SQL查询值
            else if (mapType.EqualsIgnoreCase("4"))
            {
                string kSysColumnKey = Convert.ToString(mapRow["KSysColumnKey"]);
                object o = GetTowMultilayerFieldValue(view, kSysColumnKey, 0);
                //为空直接返回
                if (o.IsNullOrEmptyOrWhiteSpace())
                {
                    return "";
                }
                //从表达式获取sql
                string sql = Convert.ToString(mapRow["KTOExpression"]);
                //为空直接返回值
                if (sql.IsNullOrEmptyOrWhiteSpace())
                {
                    return o;
                }
                SqlParam[] sqlParams = new SqlParam[] {
                            new SqlParam("@value",KDDbType.String,Convert.ToString(o))
                        };
                string v = DBUtils.ExecuteScalar<string>(view.Context, sql, "", sqlParams);
                return v;
            }
            else
            {
                string entityKey = Convert.ToString(mapRow["KSysEntityKey"]);
                string kSysColumnKey = Convert.ToString(mapRow["KSysColumnKey"]);
                object o = GetTowMultilayerFieldValue(view, kSysColumnKey, rowIndex);
                return o;
            }
        }

        #endregion

        #region 表达式处理

        /// <summary>
        /// 执行表达式
        /// </summary>
        /// <param name="view">单据界面视图</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="entityKey">单据体标识</param>
        /// <param name="pyExpression">表达式字符串</param>
        /// <returns></returns>
        public static object ExecExpression(IDynamicFormView view, int rowIndex, string entityKey, string pyExpression)
        {
            if (view == null)
            {
                return null;
            }
            try
            {

                DynamicRowModel dynamicRowModel = new DynamicRowModel(entityKey, view.BusinessInfo);
                Kingdee.BOS.Scripting.BOSExpression condition = new Kingdee.BOS.Scripting.BOSExpression(pyExpression, ExpressionKind.Expression, null, false);
                VerifyExpressionParameter para = new VerifyExpressionParameter(dynamicRowModel, condition, null);
                DynamicObject activeRow = FormBusinessServiceUtil.GetActiveRow(view.Model, entityKey, rowIndex);
                para.Context = view.Context;
                para.ActiveRow = activeRow;
                return CalcExprParser.GetExpressionValue(para);
            }
            catch (Exception ex)
            {
                string msg = string.Format("单据【{0}】【{1}】的表达式【{2}】计算失败！", view.BusinessInfo.GetForm().Name, entityKey, pyExpression);
                throw new Exception(msg + ex.Message);
            }
        }

        /// <summary>
        /// 条件表达式解析用这个
        /// </summary>
        /// <param name="view">单据界面视图</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="entityKey">单据体标识</param>
        /// <param name="pyExpression">表达式字符串</param>
        /// <returns></returns>
        public static object analysisConditionalExpression(IDynamicFormView view, int rowIndex, string entityKey, string pyExpression)
        {
            if (view == null)
            {
                return null;
            }
            try
            {
                if (entityKey.IsNullOrEmptyOrWhiteSpace())
                {
                    entityKey = view.Model.BusinessInfo.Entrys[0].Key;
                }
                ExpressionKind kind = ExpressionKind.Expression;
                Kingdee.BOS.Scripting.BOSExpression expression = new Kingdee.BOS.Scripting.BOSExpression(pyExpression, kind, null, false);
                ExpressionContext expContext = GetExpContext(view, entityKey, rowIndex);
                object result = CalcExprParser.DefaultEvaluator.Run(expression, expContext);

                return result;
            }
            catch (Exception ex)
            {
                string msg = string.Format("单据【{0}】【{1}】的表达式【{2}】计算失败！", view.BusinessInfo.GetForm().Name, entityKey, pyExpression);
                throw new Exception(msg + ex.Message);
            }
        }

        /// <summary>
        /// 执行表达式
        /// </summary>
        /// <param name="view">单据界面视图</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="entityKey">单据体标识</param>
        /// <param name="pyExpression">表达式字符串</param>
        /// <returns></returns>
        public static object ExecutionExpression(IDynamicFormView view, int rowIndex, string entityKey, string pyExpression)
        {
            if (view == null)
            {
                return null;
            }
            try
            {
                if (entityKey.IsNullOrEmptyOrWhiteSpace())
                {
                    entityKey = view.Model.BusinessInfo.Entrys[0].Key;
                }
                string value = string.Empty;
                int num = pyExpression.IndexOf("=", StringComparison.OrdinalIgnoreCase);
                if (num >= 0)
                {
                    string text2 = pyExpression.Substring(0, num).Trim();
                    string text3 = pyExpression.Substring(num + 1);
                    if (view.BillBusinessInfo.ContainsKey(text2) && !text3.StartsWith("="))
                    {
                        value = text2;
                    }
                }
                bool flag = !value.IsNullOrEmptyOrWhiteSpace();
                ExpressionKind kind = flag ? ExpressionKind.Script : ExpressionKind.Expression;
                Kingdee.BOS.Scripting.BOSExpression expression = new Kingdee.BOS.Scripting.BOSExpression(pyExpression, kind, null, false);
                ExpressionContext expContext = GetExpContext(view, entityKey, rowIndex);
                object result = CalcExprParser.DefaultEvaluator.Run(expression, expContext);

                return result;
            }
            catch (Exception ex)
            {
                string msg = string.Format("单据【{0}】【{1}】的表达式【{2}】计算失败！", view.BusinessInfo.GetForm().Name, entityKey, pyExpression);
                throw new Exception(msg + ex.Message);
            }
        }

        public static object ExecutionRkExpression(IDynamicFormView view, int rowIndex, string entityKey, string pyExpression)
        {
            if (view == null)
            {
                return null;
            }
            try
            {
                if (entityKey.IsNullOrEmptyOrWhiteSpace())
                {
                    entityKey = view.Model.BusinessInfo.Entrys[0].Key;
                }
                string value = string.Empty;
                int num = pyExpression.IndexOf("=", StringComparison.OrdinalIgnoreCase);
                if (num >= 0)
                {
                    string text2 = pyExpression.Substring(0, num).Trim();
                    string text3 = pyExpression.Substring(num + 1);
                    if (view.BillBusinessInfo.ContainsKey(text2) && !text3.StartsWith("="))
                    {
                        value = text2;
                    }
                }
                bool flag = !value.IsNullOrEmptyOrWhiteSpace();
                ExpressionKind kind = flag ? ExpressionKind.Script : ExpressionKind.Expression;
                ExpressionContext expContext = GetExpContext(view, entityKey, rowIndex);

                BOSExpression bOSExpression = new BOSExpression(pyExpression, kind, null, false);
                object result = CalcExprParser.DefaultEvaluator.Run(bOSExpression, expContext);
                return result;
            }
            catch (Exception ex)
            {
                string msg = string.Format("单据【{0}】【{1}】的表达式【{2}】计算失败！", view.BusinessInfo.GetForm().Name, entityKey, pyExpression);
                throw new Exception(msg + ex.Message);
            }
        }

        private static ExpressionContext GetExpContext(IDynamicFormView billView, string entityKey, int rowIndex)
        {
            Kingdee.BOS.Orm.DataEntity.DynamicObject activeRow = FormBusinessServiceUtil.GetActiveRow(billView.Model, entityKey, rowIndex);
            BOSDynamicRow bosdynamicRow = new BOSDynamicRow(activeRow, entityKey, billView.Model);
            object obj = new System.Dynamic.ExpandoObject();
            if (GetExpContextObject.p__Site3 == null)
            {
                GetExpContextObject.p__Site3 = CallSite<Func<CallSite, object, BusinessInfo, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "ActiveInfo", typeof(KAndOSysSynTool), new CSharpArgumentInfo[]
                {
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                }));
            }
            GetExpContextObject.p__Site3.Target(GetExpContextObject.p__Site3, obj, billView.BillBusinessInfo);
            if (GetExpContextObject.p__Site4 == null)
            {
                GetExpContextObject.p__Site4 = CallSite<Func<CallSite, object, BOSDynamicRow, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "ActiveObject", typeof(KAndOSysSynTool), new CSharpArgumentInfo[]
                {
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                }));
            }
            GetExpContextObject.p__Site4.Target(GetExpContextObject.p__Site4, obj, bosdynamicRow);
            FunctionManage functionLib = FunctionServiceHelper.GetFunctionLib(billView.Context);
            if (GetExpContextObject.p__Site5 == null)
            {
                GetExpContextObject.p__Site5 = CallSite<Func<CallSite, Type, Context, object, FunctionManage, BOSFuncExpressionContext>>.Create(Binder.InvokeConstructor(CSharpBinderFlags.None, typeof(KAndOSysSynTool), new CSharpArgumentInfo[]
                {
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null),
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                    CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                }));
            }
            return GetExpContextObject.p__Site5.Target(GetExpContextObject.p__Site5, typeof(BOSFuncExpressionContext), billView.Context, obj, functionLib).BindGetField(new TryGetValueHandler(bosdynamicRow.TryGetMember)).BindSetField(new TrySetValueHandler(bosdynamicRow.TrySetMember));
        }

        [CompilerGenerated]
        private static class GetExpContextObject
        {
            // Token: 0x040017EC RID: 6124
            public static CallSite<Func<CallSite, object, BusinessInfo, object>> p__Site3;

            // Token: 0x040017ED RID: 6125
            public static CallSite<Func<CallSite, object, BOSDynamicRow, object>> p__Site4;

            // Token: 0x040017EE RID: 6126
            public static CallSite<Func<CallSite, Type, Context, object, FunctionManage, BOSFuncExpressionContext>> p__Site5;
        }

        #endregion

        #region 金蝶调用第三方接口返回结果回写金蝶
        /// <summary>
        /// 按第三方系统返回结果给金蝶业务对象赋值，只支持单据头
        /// </summary>
        /// <param name="view"></param>
        /// <param name="map"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public static void SetViewValueByReturnResult(IDynamicFormView view, DynamicObject map, JSONObject order, string fPrecondition, int requestId)
        {
            DynamicObjectCollection entitys = map["FEntity"] as DynamicObjectCollection;
            foreach (var fieldObject in entitys)
            {
                SetViewFieldValueByJson(view, fieldObject, order, fPrecondition, requestId);
            }
        }

        /// <summary>
        /// 设置视图列的值
        /// </summary>
        /// <param name="view"></param>
        /// <param name="fieldObject"></param>
        /// <param name="value"></param>
        public static void SetViewFieldValueByJson(IDynamicFormView view, DynamicObject fieldObject, JSONObject order, string fPrecondition, int requestId)
        {
            object value;
            //同步类型
            string mapType = Convert.ToString(fieldObject["MapType"]);
            //金蝶列
            string kSysColumnKey = Convert.ToString(fieldObject["KSysColumnKey"]);
            //第三方系统列
            string oSysColumnKey = Convert.ToString(fieldObject["OSysColumnKey"]);
            //常量的方式 
            if (mapType.EqualsIgnoreCase("1"))
            {
                value = fieldObject["OSysColumnName"];
                view.Model.SetValue(kSysColumnKey, value, 0);
            }
            else
            {
                if (fPrecondition == "FIsSubSynOA=true" || fPrecondition == "FIsSubSynOA2=true" && order == null)
                {
                    JSONObject newJob = new JSONObject();
                    newJob.Add("requestid", requestId);
                    order = newJob;
                }

                if (!order.ContainsKey(oSysColumnKey))
                {
                    throw new Exception(string.Format("返回结果不包含【{0}】标识，请检查返回结果反写的同步映射配置", oSysColumnKey));
                }
                Field field = view.BusinessInfo.GetField(kSysColumnKey);
                value = order.Get(oSysColumnKey);
                //单选辅助资料列
                //AssistantField assistantField = field as AssistantField;
                //基础资料列
                BaseDataField dataField = field as BaseDataField;
                //是基础资料列
                if (dataField != null)
                {
                    view.Model.SetItemValueByNumber(kSysColumnKey, Convert.ToString(value), 0);
                }
                else if (field != null)
                {
                    view.Model.SetValue(kSysColumnKey, value, 0);
                }
            }

        }

        public static string GetWorkCode(Context context, string receiverId)
        {
            long userId = context.UserId;
            string workcode = "";
            var res = WebApiServiceCall.ExecuteBillQuery(context, QueryParameter("SEC_User", "F_YCVN_GH", $"FUserID={receiverId}"));
            if (res.Count > 0)
            {
                workcode = res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return workcode;
        }

        private static string QueryParameter(string formId, string fieldKeys, string filterString)
        {
            var param = new
            {
                FormId = formId,
                FieldKeys = fieldKeys,
                FilterString = filterString
            };
            return JsonConvert.SerializeObject(param);
        }

        #endregion
    }
}
